﻿using System;
using System.Collections.Generic;
using System.Text;
using Tsanie.DmPoster.Event;

namespace Tsanie.DmPoster.Models {
    public class BiliPosComment : BiliComment {
        /// <summary>BiliPos弹幕内容</summary>
        public override string Message {
            get { return base.Message; }
            set {
                if (this.Mode == 7 && !ExecuteCommentMessage(this, value))
                    throw new BiliException("“" + value + "”" + "弹幕内容不合法！");
                base.Message = value;
                if (_propertyChanged != null)
                    _propertyChanged(this, BiliProperty.Message);
            }
        }

        private int x;
        /// <summary>BiliPos弹幕横坐标 x</summary>
        public new int X {
            get { return this.x; }
            set {
                this.x = value;
                base.X = value;
                base.Message = GetPosMessage(this);
            }
        }
        private void SetX(int x) {
            this.x = x;
            base.X = x;
        }

        private int y;
        /// <summary>BiliPos弹幕纵坐标 y</summary>
        public new int Y {
            get { return this.y; }
            set {
                this.y = value;
                base.Y = value;
                base.Message = GetPosMessage(this);
            }
        }
        private void SetY(int y) {
            this.y = y;
            base.Y = y;
        }

        private float a1;
        /// <summary>BiliPos弹幕起始透明度</summary>
        public float A1 {
            get { return this.a1; }
            set {
                SetA1(value);
                base.Message = GetPosMessage(this);
            }
        }
        private void SetA1(float value) {
            if (value < 0 || value > 1)
                throw new BiliException("“" + value + "”" + "弹幕起始透明度不合法！");
            this.a1 = value;
        }

        private float a2;
        /// <summary>BiliPos弹幕终止透明度</summary>
        public float A2 {
            get { return this.a2; }
            set {
                SetA2(value);
                base.Message = GetPosMessage(this);
            }
        }
        private void SetA2(float value) {
            if (value < 0 || value > 1)
                throw new BiliException("“" + value + "”" + "弹幕终止透明度不合法！");
            this.a2 = value;
        }

        /// <summary>BiliPos弹幕生存时间</summary>
        public override float Life {
            get { return this.life; }
            set {
                SetLife(value);
                base.Message = GetPosMessage(this);
            }
        }

        private string realMsg;
        /// <summary>BiliPos弹幕内容</summary>
        public string RealMsg {
            get { return this.realMsg; }
            set {
                SetRealMsg(value);
                base.Message = GetPosMessage(this);
            }
        }
        private void SetRealMsg(string value) {
            if (string.IsNullOrEmpty(value))
                throw new BiliException("“" + value + "”" + "弹幕内容不可为空！");
            this.realMsg = value;
        }

        private int? rz;
        /// <summary>BiliPos弹幕Z轴旋转角度</summary>
        public int RotateZ {
            get { return (rz.HasValue ? rz.Value : -1); }
            set {
                SetRZ(value);
                base.Message = GetPosMessage(this);
            }
        }
        internal float rzValue;
        private void SetRZ(int value) {
            if (value < 0 || value > 360)
                throw new BiliException("“" + value + "”" + "弹幕Z轴旋转角度不合法！");
            this.rz = value;
            this.rzValue = 2 * (float)Math.PI * (value / 360f);
            //comm.rzFloat = 2 * (float)Math.PI * (comm.RotateZ / 360f);
        }

        private int? ry;
        /// <summary>BiliPos弹幕Y轴旋转角度</summary>
        public int RotateY {
            get { return (ry.HasValue ? ry.Value : -1); }
            set {
                SetRY(value);
                base.Message = GetPosMessage(this);
            }
        }
        internal float ryValue;
        private void SetRY(int value) {
            if (value < 0 || value > 360)
                throw new BiliException("“" + value + "”" + "弹幕Y轴旋转角度不合法！");
            this.ry = value;
            this.ryValue = (Math.Abs(180f - value) - 90f) / 90f;
            //int tan = comm.RotateY % 360;
            //float fx = (Math.Abs(180f - tan) - 90f) / 90f;
            //comm.ryFloat = fx;
        }

        //internal float? rzFloat;
        //internal float? ryFloat;

        private static string GetPosMessage(BiliPosComment comm) {
            return "[\"" + comm.x + "\",\"" + comm.y
                + "\",\"" + comm.a1 + "-" + comm.a2
                + "\",\"" + comm.life + "\",\"" + comm.realMsg
                + ((comm.rz.HasValue) ? ("\",\"" + comm.rz + "\",\"" + comm.ry) : (""))
                + "\"]";
        }
        private static bool ExecuteCommentMessage(BiliPosComment comm, string message) {
            if (string.IsNullOrEmpty(message))
                // 为空
                return false;
            if (message[0] != '[' || message[message.Length - 1] != ']')
                // 不是“[...]”这种格式
                return false;
            // [x,y,alpha,life,msg,rz,ry]
            try {
                string[] pars = message.Substring(2, message.Length - 4).Split(
                    new string[] { "\",\"" }, StringSplitOptions.None);
                if (pars.Length != 5 && pars.Length != 7)
                    return false;

                comm.SetX(int.Parse(pars[0]));
                comm.SetY(int.Parse(pars[1]));
                string[] alpha = pars[2].Split('-');
                comm.SetA1(float.Parse(alpha[0]));
                comm.SetA2(float.Parse(alpha[1]));
                comm.SetLife(float.Parse(pars[3]));
                comm.SetRealMsg(pars[4]);

                if (pars.Length == 7) {
                    comm.SetRZ(int.Parse(pars[5]));
                    comm.SetRY(int.Parse(pars[6]));
                }
                return true;
            } catch (Exception e) {
                throw new BiliException("“" + message + "”" + e.Message, e);
            }
        }
    }
}
